package org.zf.database.util;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.pool.DruidPooledConnection;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.zf.database.domain.DBInfo;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 数据库连接池管理
 */
@Slf4j
public class DruidUtil
{
    public static Map<String, DruidDataSource> map = new ConcurrentHashMap<>();

    @SneakyThrows
    public static Connection getConn(DBInfo dbInfo)
    {
        try
        {
            DruidDataSource source = (DruidDataSource) getDataSource(dbInfo);
            log.info("当前数据库连接池的量为：" + source.getActiveCount() + " : " + source.getActivePeak());
            return (DruidPooledConnection) source.getPooledConnection();
        } catch (SQLException throwables)
        {
            throw ExceptionUtil.getRootCause(throwables);
        }
    }

    public static DataSource getDataSource(DBInfo dbInfo) throws Exception
    {
        String key = String.format("%s_%s_%s", dbInfo.getJdbcUrl(), dbInfo.getConnInfo().getUser(), dbInfo.getConnInfo().getPasswd());
        DruidDataSource source = map.get(key);
        if (source == null)
            source = initDataSource(dbInfo);
        return source;
    }

    private static DruidDataSource initDataSource(DBInfo dbInfo) throws Exception
    {
        Properties prop = new Properties();
        prop.setProperty("driver", dbInfo.getDbType().getDriverClass());
        prop.setProperty("url", dbInfo.getJdbcUrl());
        prop.setProperty("connectionProperties", "useUnicode=true;characterEncoding=UTF8");
        prop.setProperty("username", dbInfo.getConnInfo().getUser());
        prop.setProperty("password", dbInfo.getConnInfo().getPasswd());
        prop.setProperty("initialSize", "1");
        prop.setProperty("maxActive", "50");
        prop.setProperty("minIdle", "3");
        prop.setProperty("maxWait", "60000");
        prop.setProperty("filters", "stat");
        prop.setProperty("timeBetweenEvictionRunsMillis", "35000");
        prop.setProperty("minEvictableIdleTimeMillis", "30000");
        prop.setProperty("testWhileIdle", "true");
        prop.setProperty("testOnBorrow", "false");
        prop.setProperty("testOnReturn", "false");
        prop.setProperty("poolPreparedStatements", "false");
        prop.setProperty("maxPoolPreparedStatementPerConnectionSize", "200");
        prop.setProperty("removeAbandoned", "true");
        try
        {
            DruidDataSource druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(prop);
            map.put(StrUtil.format("{}_{}_{}", dbInfo.getJdbcUrl(), dbInfo.getConnInfo().getUser(), dbInfo.getConnInfo().getPasswd()), druidDataSource);
            return druidDataSource;
        } catch (Exception e)
        {
            log.error("初始化创建连接池失败", e);
            throw e;
        }
    }
}
